package datetime

import (
	"strconv"
	"time"
)

type DateFormat string

const (
	YYYY                DateFormat = "2006"                // 年
	YYYY_MM             DateFormat = "2006-01"             // 年月
	YYYY_MM_DD          DateFormat = "2006-01-02"          // 年月日
	YYYY_MM_DD_HH       DateFormat = "2006-01-02 15"       // 年月日 时
	YYYY_MM_DD_HH_MM    DateFormat = "2006-01-02 15:04"    // 年月日 时分
	YYYY_MM_DD_HH_MM_SS DateFormat = "2006-01-02 15:04:05" // 年月日 时分秒
)

// Time2Date time.Time 转 date
func Time2Date(date time.Time, format DateFormat) string {
	return date.Format(string(format))
}

// DateStr2Time 日期字符串 => time.Time
func DateStr2Time(str string, format DateFormat) time.Time {
	t, _ := time.ParseInLocation(string(format), str, time.Local)
	return t
}

// DateStr2Timestamp 日期字符串 => 时间戳
func DateStr2Timestamp(str string, format DateFormat) int64 {
	now, _ := time.ParseInLocation(string(format), str, time.Local)
	return now.Unix()
}

// EndOfDate end of date
func EndOfDate(t time.Time) time.Time {
	return time.Date(t.Year(), t.Month(), t.Day(), 23, 59, 59, 0, time.Local)
}

// EndOfToday end of today
func EndOfToday() time.Time {
	return EndOfDate(time.Now())
}

// EndOfWeek end of week
func EndOfWeek(t time.Time) time.Time {
	return StartOfWeek(t.AddDate(0, 0, 7)).Add(time.Second * -1)
}

// EndOfThisWeek end of this week
func EndOfThisWeek() time.Time {
	return EndOfWeek(time.Now())
}

// EndOfMonth end of month
func EndOfMonth(t time.Time) time.Time {
	return StartOfMonth(t.AddDate(0, 1, 0)).Add(time.Second * -1)
}

// EndOfThisMonth end of this month
func EndOfThisMonth() time.Time {
	return EndOfMonth(time.Now())
}

// EndOfYear end of year
func EndOfYear(t time.Time) time.Time {
	return StartOfYear(t.AddDate(1, 0, 0)).Add(time.Second * -1)
}

// EndOfThisYear end of this year
func EndOfThisYear() time.Time {
	return EndOfYear(time.Now())
}

// StartOfDate start of date
func StartOfDate(t time.Time) time.Time {
	return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.Local)
}

// StartOfToday start of today
func StartOfToday() time.Time {
	return StartOfDate(time.Now())
}

// StartOfWeek start of week
func StartOfWeek(t time.Time) time.Time {
	var (
		add int
		w   = t.Weekday()
	)
	switch w {
	case time.Sunday:
		add = -6
	default:
		add = 1 - int(w)
	}
	return StartOfDate(t.AddDate(0, 0, add))
}

// StartOfThisWeek start of this week
func StartOfThisWeek() time.Time {
	return StartOfWeek(time.Now())
}

// StartOfMonth start of month
func StartOfMonth(t time.Time) time.Time {
	return time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, time.Local)
}

// StartOfThisMonth start of this month
func StartOfThisMonth() time.Time {
	return StartOfMonth(time.Now())
}

// StartOfYear start of year
func StartOfYear(t time.Time) time.Time {
	return time.Date(t.Year(), 1, 1, 0, 0, 0, 0, time.Local)
}

// StartOfThisYear start of this year
func StartOfThisYear() time.Time {
	return StartOfYear(time.Now())
}

// NDaysAfter end of n days after
func NDaysAfter(n int) time.Time {
	return EndOfToday().AddDate(0, 0, n)
}

// ExcelDate2Time excel日期转datetime 17876 => time.Time
func ExcelDate2Time(excelDate string) (bool, time.Time) {
	excelTime := time.Date(1899, time.December, 30, 0, 0, 0, 0, time.UTC)
	days, err := strconv.Atoi(excelDate)
	if err != nil {
		return false, excelTime
	}
	return true, excelTime.Add(time.Second * time.Duration(days*86400))
}
